<template>
  <div class="vue-container">
    <common-form
      ref="commonForm"
      :disabled="disabled"
      :options="options"
      @handlerClick="handlerClick"
      @advancedSearch="getList"
    >
      <template slot="advanced-content">
        <el-form ref="advancedForm" style="margin-top: 20px;" :model="queryForm" label-width="80px">
          <el-form-item label="菜单名称">
            <el-input v-model="queryForm.label" clearable />
          </el-form-item>
          <el-form-item label="菜单状态">
            <el-select
              v-model="queryForm.status"
              style="width: 100%;"
              clearable
              placeholder="请选择菜单状态"
            >
              <el-option
                v-for="(item, index) in statusList"
                :key="index"
                :value="Number(item.code)"
                :label="item.label"
              />
            </el-select>
          </el-form-item>
        </el-form>
      </template>
    </common-form>
    <common-table
      :table-data="data"
      :columns="columns"
      :height="height"
      :table-tree="true"
      :table-expand="defaultUnfoldVal"
      :loading="loading"
      @expandChange="expandChange"
    >
      <!-- 菜单图标 -->
      <template #icon="scope">
        <svg-icon v-if="scope.row.icon && getType(scope.row.icon)" :icon-class="scope.row.icon" :size="16" style="width: 48px;" />
      </template>
      <!-- 菜单状态 -->
      <template #status="scope">
        <el-popconfirm
          v-if="scope.row.type !== 3"
          v-permission="{ permission: 'system:menu:update', disabled }"
          :title="scope.row.status === 1 ? '确定要禁用该菜单吗？' : '确定要启用该菜单吗？'"
          icon=""
          @confirm="popConfirm(scope.row)"
        >
          <el-switch
            slot="reference"
            v-model="scope.row.status"
            v-permission="{ permission: 'system:menu:update', disabled }"
            :active-value="1"
            :inactive-value="2"
            @change="switchChange($event, scope.row)"
          />
        </el-popconfirm>
      </template>
      <!-- 显示状态 -->
      <template #showStatus="scope">
        <el-tag v-if="scope.row.showStatus === 2 && scope.row.type !== 3" type="danger">隐藏</el-tag>
        <el-tag v-else-if="scope.row.showStatus === 1 && scope.row.type !== 3">显示</el-tag>
      </template>
      <template #createTime="scope">
        {{ scope.row.createTime | formatTime }}
      </template>
      <!-- 列表操作按钮-->
      <template #operation="scope">
        <el-button
          v-if="scope.row.type !== 3"
          v-throttle
          v-permission="'system:menu:create'"
          :size="size"
          type="text"
          icon="el-icon-plus"
          @click.stop="handlerRowSave(scope.row)"
        >新增</el-button>
        <el-button
          v-throttle
          v-permission="'system:menu:update'"
          :size="size"
          type="text"
          icon="el-icon-edit-outline"
          @click.stop="handlerSave(scope.row)"
        >编辑</el-button>
        <el-button
          v-throttle
          v-permission="'system:menu:del'"
          :size="size"
          type="text"
          icon="el-icon-delete"
          class="danger-btn"
          @click.stop="handlerDel(funs['del'], scope.row)"
        >删除</el-button>
      </template>
    </common-table>
    <!-- 新增or编辑组件 -->
    <add-or-update ref="addOrUpdate" :obj="{ typeList,statusList,showStatusList }" @ok="getList" />
    <!-- 全局导入组件 -->
    <to-channel ref="toChannel" title="角色导入" @change="getList" />
  </div>
</template>
<script>
import { mixin } from '@/views/pages/mixin'
import AddOrUpdate from './components/save'
import { arrayToTree, treeToArray } from '@/utils'
export default {
  name: 'Menu',
  components: {
    AddOrUpdate
  },
  mixins: [mixin],
  data() {
    return {
      typeList: [], // 菜单类型数组
      statusList: [], // 菜单状态数组
      showStatusList: [], // 菜单显示状态数组
      // 默认展开数组
      defaultUnfoldVal: [],
      listData: [], // 表格树数据转化的扁平list
      // 表头数组
      columns: [
        {
          prop: 'label',
          label: '菜单名称',
          align: 'left'
        },
        {
          type: 'slot',
          slotType: 'icon',
          width: '70',
          label: '菜单图标'
        },
        {
          prop: 'path',
          label: '路由地址'
        },
        {
          prop: 'component',
          label: '组件路径'
        },
        {
          prop: 'permission',
          label: '权限字符'
        },
        {
          type: 'slot',
          slotType: 'status',
          label: '菜单状态'
        },
        {
          type: 'slot',
          slotType: 'showStatus',
          width: '80',
          label: '显示状态'
        },
        {
          prop: 'sort',
          width: '70',
          label: '排序'
        },
        {
          prop: 'createTime',
          type: 'slot',
          slotType: 'createTime',
          label: '创建时间'
        },
        {
          type: 'slot',
          prop: 'operation',
          label: '操作',
          width: '188',
          slotType: 'operation',
          align: 'center',
          fixed: 'right'
        }
      ],
      // 顶部表单按钮组
      options: [{
        type: 'button',
        icon: 'el-icon-refresh',
        handler: 'handlerRefresh',
        float: 'left',
        class: 'refreshBtn',
        text: '刷新'
      },
      {
        type: 'button',
        icon: 'el-icon-plus',
        handler: 'handlerSave',
        float: 'left',
        btnType: 'primary',
        permission: 'create',
        text: '新增'
      },
      {
        type: 'button',
        handler: 'handlerReset',
        permission: 'tree',
        float: 'right',
        class: 'infoBtn',
        text: '重置'
      },
      {
        type: 'button',
        handler: 'handlerQuery',
        permission: 'tree',
        float: 'right',
        text: '查询',
        btnType: 'primary'
      },
      {
        type: 'search',
        bindValue: '',
        permission: 'tree',
        float: 'right',
        label: 'keyword',
        handler: 'handlerQuery',
        placeholder: '输入关键字搜索'
      }
      ],
      // 查询对象
      queryForm: {
        parentId: '0'
      },
      // 是否分页
      isPage: false
    }
  },
  async created() {
    // 通过全局方法取数据字典
    this.typeList = await this.getDictInfo('menu_type')
    this.statusList = await this.getDictInfo('dict_status')
    this.showStatusList = await this.getDictInfo('menu_show_status')
  },
  methods: {
    // 判断图标是否来自el或者icons
    getType(icon) {
      const list = import.meta.globEager('../../../../assets/icons/*.svg')
      return !icon.includes('el-') ? list[`../../../../assets/icons/${icon}`] : true
    },
    // 搜索
    handlerQuery() {
      const row = this.options.find((item) => item.type === 'search')
      const keyword = row.bindValue
      const list = this.listData.filter(item => {
        return item.label.indexOf(keyword) > -1 ||
          (item.path && item.path.indexOf(keyword) > -1) ||
          (item.component && item.component.indexOf(keyword) > -1)
      })
      this.data = arrayToTree(list, 'children')
      if (this.data.length && row.bindValue) {
        this.defaultUnfoldVal = [this.data[0].id]
      }
    },
    // 重置
    handlerReset() {
      this.options.find((item) => item.type === 'search').bindValue = ''
      this.getList()
    },
    // 获取列表数据
    getList() {
      this.loading = true
      const queryForm = { ...this.queryForm }
      this.funs['tree'](queryForm).then((res) => {
        this.data = res.data
        this.listData = treeToArray(JSON.parse(JSON.stringify(res.data)), 'children')
        if (this.data.length > 0 && !this.defaultUnfoldVal.length) {
          this.defaultUnfoldVal = [this.data[0].id]
        }
      }).finally(() => {
        this.loading = false
      })
    },
    // 状态切换触发
    switchChange(e, form) {
      form.status = e === 1 ? 2 : 1
    },
    // 确认禁用或启用
    popConfirm(form) {
      this.loading = true
      form.status = form.status === 1 ? 2 : 1
      this.funs['edit'](form).then(() => {
        if (form.status === 1) {
          this.$message.success('菜单已启用')
        } else {
          this.$message.error('菜单已禁用')
        }
      }).catch(e => {
        form.status = form.status === 1 ? 2 : 1
      }).finally(() => {
        this.loading = false
      })
    },
    // 行新增
    handlerRowSave(row) {
      if (row.type === 3) {
        return
      }
      const item = {
        parentId: row.id,
        type: row.type + 1,
        sort: 0,
        status: 1,
        showStatus: 1
      }
      this.$refs.addOrUpdate.openDialog(item)
    },
    // 表格展开或收起监听
    expandChange({ val, expanded }) {
      const idx = this.defaultUnfoldVal.findIndex(item => item === val.id)
      if (expanded) {
        this.defaultUnfoldVal.push(val.id)
      } else {
        if (val.parentId !== '0') this.defaultUnfoldVal.splice(idx, 1)
        else this.defaultUnfoldVal = []
      }
    }
  }
}
</script>
